package com.murong.ai.chat.domain.speech2text.leopard;

import ai.picovoice.leopard.Leopard;
import ai.picovoice.leopard.LeopardException;
import ai.picovoice.leopard.LeopardTranscript;
import com.murong.ai.chat.domain.speech2text.STTService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.sound.sampled.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;

@Service
public class LeopardSTTService implements STTService {
    private static Long silenceTimeout;
    private static Integer frameLength;
    private ArrayList<Short> pcmBuffer = null;
    @Autowired
    Leopard leopard;
    @Autowired
    private TargetDataLine microphone;
    @Autowired
    private AudioFormat audioFormat;


    @SneakyThrows
    public LeopardSTTService(Environment environment) {
        silenceTimeout=environment.getProperty("leopard.silence.timeout",Long.class);
        frameLength=environment.getProperty("leopard.buffer.frame.length",Integer.class);
    }

    @SneakyThrows
    @Override
    public String execute() {
        try {
//            leopard = new Leopard.Builder().setAccessKey(accessKey).build();
            pcmBuffer=new ArrayList<>();
            //microphone.start();

            byte[] buffer = new byte[frameLength * 2];
            long lastSpeechTime = System.currentTimeMillis();

            ByteBuffer captureBuffer =ByteBuffer.wrap(buffer);
            captureBuffer.order(ByteOrder.LITTLE_ENDIAN);
            short[] shortBuffer = new short[frameLength];

            while (true) {
                // 读取音频数据
                int bytesRead = microphone.read(captureBuffer.array(), 0, captureBuffer.capacity());
                if (bytesRead > 0) {

                    captureBuffer.asShortBuffer().get(shortBuffer);
                    for (short value : shortBuffer) {
                        this.pcmBuffer.add(value);
                    }

                    boolean currentIsSpeaking = calculateVolume(captureBuffer.array(), bytesRead);
                    if (currentIsSpeaking) {
                        lastSpeechTime = System.currentTimeMillis();
                    } else {
                        long currentTime = System.currentTimeMillis();
                        long diffTime = currentTime - lastSpeechTime;
                        if (diffTime > silenceTimeout) {
                            break;
                        }
                    }
                }
            }

            // 处理音频帧
            LeopardTranscript transcript = leopard.process(getPCM());
            if (transcript != null) {
                return transcript.getTranscriptString();
            }

            // 释放资源
//            microphone.stop();
//            microphone.close();
            leopard.delete();
        } catch (LeopardException  e) {
            e.printStackTrace();
        }
        return null;
    }


    private boolean calculateVolume(byte[] buffer, int bytesRead) {
        long sum = 0;
        for (int i = 0; i < bytesRead; i++) {
            sum += Math.abs(buffer[i]);
        }
        double average = sum / (double) bytesRead;
        double volume = (average / 128);
        if(volume>0.3){
            return true;
        }else {
            return false;
        }
    }

    public short[] getPCM() {
        short[] pcm = new short[this.pcmBuffer.size()];
        for (int i = 0; i < this.pcmBuffer.size(); ++i) {
            pcm[i] = this.pcmBuffer.get(i);
        }
        return pcm;
    }
}
